package com.linkit.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.conn.ConnectTimeoutException;
import org.json.JSONObject;

import android.util.Log;

import com.linkit.exception.ErrorCodes;
import com.linkit.exception.FTExceptions;
import com.linkit.model.HttpParams;

/**
 * kết nối, lấy dữ liệu từ server và xử lý timeout
 * 
 * @author lunnd
 * 
 */

public class ServiceUtils {
	public static final int CONTENT_TYPE_TEXT = 0;
	public static final int CONTENT_TYPE_JSON = 1;

	public ServiceUtils() {

	}

	/**
	 * Lấy dữ liệu từ server bằng cách truyền url
	 * 
	 * @param strUrl
	 * @return
	 * @throws IOException
	 */
	public static String getServiceByGet(HttpParams configParameters)
			throws Exception {
		String data = "";
		InputStream iStream = null;
		HttpURLConnection urlConnection = null;
		try {
			String strUrl = convertURL(configParameters, true,
					CONTENT_TYPE_TEXT);
			URL url = new URL(strUrl);
			Log.i(Constants.TAG, url.toString());
			// Creating an http connection to communicate with url
			urlConnection = (HttpURLConnection) url.openConnection();

			// Thiết lập timeout
			urlConnection.setConnectTimeout(Constants.TIMEOUT_MILLISEC);
			urlConnection.setReadTimeout(Constants.TIMEOUT_MILLISEC);

			// Kết nối đến tài nguyên
			urlConnection.connect();

			// lấy mã kết quả
			int responseCode = urlConnection.getResponseCode();

			if (responseCode == HttpURLConnection.HTTP_OK) {
				// Reading data from url
				iStream = urlConnection.getInputStream();

				BufferedReader br = new BufferedReader(new InputStreamReader(
						iStream));

				StringBuffer sb = new StringBuffer();

				String line = "";
				while ((line = br.readLine()) != null) {
					sb.append(line);
				}

				data = sb.toString().trim();

				br.close();
				
			} else {
				Log.e(Constants.TAG, "Response Code:" + responseCode);
			}

		} catch (MalformedURLException e) {// xảy ra khi url không đúng định
											// dạng
			Log.e(Constants.TAG, e.toString());
		} catch (ConnectException e) {
			// Xảy ra khi kết nối bị từ chối
			throw new FTExceptions(ErrorCodes.REFUSE_CONNECTION);
		} catch (ConnectTimeoutException e) {
			// xảy ra khi thời gian kết nối vượt quá mức cho phép
			throw new FTExceptions(ErrorCodes.TIMEOUT_CONNECTION);
		} catch (SocketTimeoutException e) {
			// xảy ra khi thời gian kết nối vượt quá mức cho phép
			throw new FTExceptions(ErrorCodes.TIMEOUT_CONNECTION);
			
		} finally {

			if (iStream != null) {

				try {
					iStream.close();
				} catch (IOException e) {

					Log.e(Constants.TAG, e.getMessage());
				}
			}

			if (urlConnection != null) {
				urlConnection.disconnect();
			}


		}

		return data;
	}

	/**
	 * Lấy dữ liệu từ server bằng cách truyền theo phương thức POST
	 * 
	 * @param strUrl
	 * @return
	 * @throws IOException
	 */
	public static String getServiceByPost(HttpParams configParameters)
			throws FTExceptions {
		String data = "";
		InputStream iStream = null;
		HttpURLConnection urlConnection = null;
		String urlParameters = "";
		try {
			
			urlParameters = getQuery(configParameters.getParameters(),
					CONTENT_TYPE_JSON);
			String strUrl = convertURL(configParameters, false,
					CONTENT_TYPE_JSON);
			URL url = new URL(strUrl);
			Log.i(Constants.TAG, strUrl);
			// Creating an http connection to communicate with url
			urlConnection = (HttpURLConnection) url.openConnection();
			urlConnection.setRequestMethod("POST");
			urlConnection.setDoOutput(true);
			urlConnection.setDoInput(true);
			urlConnection.setChunkedStreamingMode(0);
			urlConnection.setInstanceFollowRedirects(false); 
			urlConnection.setUseCaches(false);
			urlConnection.setRequestProperty("Accept-Charset", Constants.CHARSET);
			urlConnection.setRequestProperty("Accept", Constants.CONTENT_TYPE_VALUE);
			urlConnection.setRequestProperty("Content-Type", Constants.CONTENT_TYPE_VALUE);
			urlConnection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
			// Thiết lập timeout
			urlConnection.setConnectTimeout(Constants.TIMEOUT_MILLISEC);
			urlConnection.setReadTimeout(Constants.TIMEOUT_MILLISEC);

			// gửi dữ liệu lên server
			OutputStream os = urlConnection.getOutputStream();
			OutputStreamWriter writer = new OutputStreamWriter(os,
					Constants.CHARSET);
			writer.write(urlParameters);
			writer.flush();
			writer.close();
			os.close();

			// Kết nối đến tài nguyên
			urlConnection.connect();

			// lấy mã kết quả
			int responseCode = urlConnection.getResponseCode();

			if (responseCode == HttpURLConnection.HTTP_OK) {
				// nhận kết quả trả về từ server
				iStream = urlConnection.getInputStream();

				BufferedReader br = new BufferedReader(new InputStreamReader(
						iStream));

				StringBuffer sb = new StringBuffer();

				String line = "";
				while ((line = br.readLine()) != null) {
					sb.append(line);
				}

				data = sb.toString().trim();

				br.close();
			} else {
				Log.e(Constants.TAG, "Response Code:" + responseCode);
			}

		} catch (MalformedURLException e) {// xảy ra khi url không đúng định
											// dạng
			Log.e(Constants.TAG, e.toString());
		} catch (ConnectException e) {// Xảy ra khi kết nối bị từ chối
			throw new FTExceptions(ErrorCodes.REFUSE_CONNECTION);
		} catch (ConnectTimeoutException e) {// xảy ra khi thời gian kết nối
												// vượt quá mức cho phép
			throw new FTExceptions(ErrorCodes.TIMEOUT_CONNECTION);
		} catch (SocketTimeoutException e) {// xảy ra khi thời gian kết nối vượt
			throw new FTExceptions(ErrorCodes.TIMEOUT_CONNECTION);
		} catch (IOException e) {// Xảy ra khi không mở một kết nối và không kết
									// nối được vởi tài nguyên
			Log.e(Constants.TAG, "Xảy ra khi không mở một kết nối và không kết nối được vởi tài nguyên:" + e.toString());
		} catch (Exception e) {
			Log.e(Constants.TAG, "Lỗi xảy ra khi lấy dữ liệu từ server:" + e.toString());
		} finally {

			if (iStream != null) {

				try {
					iStream.close();
				} catch (IOException e) {

					Log.e(Constants.TAG, e.getMessage());
				}
			}

			if (urlConnection != null) {
				urlConnection.disconnect();
			}

		}

		return data;
	}

	private static String getQuery(List<NameValuePair> parameterList,
			int ContentType) {
		String result = "";
		switch (ContentType) {
		case CONTENT_TYPE_TEXT:
			result = raiseURLParams(parameterList);
			break;

		case CONTENT_TYPE_JSON:
			result = raiseJSONParams(parameterList);
			break;
			
		default:
			break;
		}
		return result;
	}

	private static String raiseURLParams(List<NameValuePair> parameterList) {
		StringBuilder result = new StringBuilder();
		boolean first = true;
		try {

			for (NameValuePair pair : parameterList) {
				if (first)
					first = false;
				else
					result.append("&");

				result.append(URLEncoder.encode(pair.getName(), "UTF-8"));
				result.append("=");
				result.append(URLEncoder.encode(pair.getValue(), "UTF-8"));
			}

		} catch (Exception e) {
			first = true;
			if (parameterList != null && parameterList.size() > 0) {
				for (NameValuePair nameValuePair : parameterList) {
					if (first)
						first = false;
					else
						result.append("&");
					// thêm name
					result.append(nameValuePair.getName());
					result.append("=");
					result.append(nameValuePair.getValue());
				}
			}
		}

		return result.toString();
	}
	private static String raiseJSONParams(List<NameValuePair> parameterList) {
		JSONObject result = new JSONObject();
		try {
			for (NameValuePair pair : parameterList) {
				result.put(pair.getName(),pair.getValue());
			}
		} catch (Exception e) {
			Log.e(Constants.TAG,"Không thể tạo tham số json");
		}
		return result.toString();
	}

	/**
	 * Thiết lập URL
	 * 
	 * @param configParameters
	 *            : Tham số config
	 * @param isMethod
	 *            : là phương thức gửi true là GET và false là POST
	 * @return
	 */

	private static String convertURL(HttpParams configParameters,
			boolean isMethod, int contentType) {
		StringBuffer url = new StringBuffer("");
		if (configParameters != null) {

			// thêm url
			url.append(configParameters.getUrl());

			// thêm tên hàm
			url.append("/" + configParameters.getMethodName());

			// thêm các tham số
			if (isMethod) {
				ArrayList<NameValuePair> parameterList = (ArrayList<NameValuePair>) configParameters
						.getParameters();
				if(parameterList != null){
					url.append("?");
					url.append(getQuery(parameterList, contentType));
				}
			}
		}
		return url.toString();

	}
}
